﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Newtonsoft.Json;
using SalesPages.Common;
using SalesPages.Infrastructure;
using SalesPages.Service.Cache.Redis;
using System.Linq;
using StackExchange.Redis;
using System.Threading.Tasks;

namespace SalesPages.Service.Cache
{
    public partial class RedisCacheService : IRedisCacheService
    {
        #region Redis String 

        public bool StringSet<T>(string key, T value, TimeSpan? expiresAt = default(TimeSpan?), When when = When.Always, CommandFlags commandFlags = CommandFlags.None) where T : class
        {
            var stringContent = value.ToJsonString();
            return RedisManager.Connection.GetDatabase().StringSet(key, stringContent, expiresAt, when, commandFlags);
        }

        public bool StringSet<T>(string key, object value, TimeSpan? expiresAt = default(TimeSpan?), When when = When.Always, CommandFlags commandFlags = CommandFlags.None) where T : class
        {
            var stringContent = value.ToJsonString();
            return RedisManager.Connection.GetDatabase().StringSet(key, stringContent, expiresAt, when, commandFlags);
        }

        public void StringSetBatch(IList<Tuple<string, object>> caches, TimeSpan? expiresAt = default(TimeSpan?), When when = When.Always, CommandFlags commandFlags = CommandFlags.None)
        {
          
            try
            {
                var addTasks = new List<Task>();
                var batch = RedisManager.Connection.GetDatabase().CreateBatch();


                caches.ToList().ForEach(c =>
                {
                    var addAsync = batch.StringSetAsync(c.Item1, c.Item2.ToJsonString(), expiresAt, when, commandFlags);
                    addTasks.Add(addAsync);
                });
                batch.Execute();
                var tasks = addTasks.ToArray();
                Task.WaitAll(tasks);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public long StringLength(string key, CommandFlags commandFlags = CommandFlags.None)
        {
            return RedisManager.Connection.GetDatabase().StringLength(key, commandFlags);
        }

        public long StringAppend(string key, string appendVal, CommandFlags commandFlags = CommandFlags.None)
        {
            return RedisManager.Connection.GetDatabase().StringAppend(key, appendVal, commandFlags);
        }

        public string StringGetAndSet(string key, string newVal, CommandFlags commandFlags = CommandFlags.None)
        {
            return RedisManager.Connection.GetDatabase().StringGetSet(key, newVal, commandFlags).JsonStringToObj<string>();
        }

        public bool StringUpdate<T>(string key, T value, TimeSpan expiresAt, When when = When.Always, CommandFlags commandFlags = CommandFlags.None) where T : class
        {


            var stringContent = value.ToJsonString();
            return RedisManager.Connection.GetDatabase().StringSet(key, stringContent, expiresAt, when, commandFlags);

        }

        public double StringIncrement(string key, double val, CommandFlags commandFlags = CommandFlags.None)
        {


            return RedisManager.Connection.GetDatabase().StringIncrement(key, val, commandFlags);

        }

        public T StringGet<T>(string key, CommandFlags commandFlags = CommandFlags.None) where T : class
        {
            try
            {

                RedisValue myString = RedisManager.Connection.GetDatabase().StringGet(key, commandFlags);
                if (myString.HasValue && !myString.IsNullOrEmpty)
                {
                    return myString.JsonStringToObj<T>();
                }
                else
                {
                    return null;
                }

            }
            catch (Exception ex)
            {
                // Log Exception
                return null;
            }
        }

       

        #endregion

        #region Redis Public 

        public bool KeyExists(string key, CommandFlags commandFlags = CommandFlags.None)
        {
                   
            return RedisManager.Connection.GetDatabase().KeyExists(key, commandFlags);
        }

        public void DbConnectionStop()
        {

            RedisManager.Connection.Dispose();
        }

        public bool KeyRemove(string key, CommandFlags commandFlags = CommandFlags.None)
        {

            return RedisManager.Connection.GetDatabase().KeyDelete(key, commandFlags);
        }

        public void KeyRemove(RedisKey[] keys, CommandFlags commandFlags = CommandFlags.None)
        {
            RedisManager.Connection.GetDatabase().KeyDelete(keys, commandFlags);
        }

      


        #endregion

    }
}
